#include "file_manipulator.h"

#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <utils/error.h>

struct file_handler
{
  char *file_path;
  const char *filter_extension;
  FILE *file_stream;
};

file_handler_ptr
init_file_handler(const char *filter_extension)
{
  file_handler_ptr file_handler = malloc(sizeof (*file_handler));
  file_handler->file_path = NULL;
  file_handler->file_stream = NULL;
  file_handler->filter_extension = filter_extension;

  return file_handler;
}

static void
free_path(file_handler_ptr file_handler)
{
  if (file_handler->file_path != NULL)
    free(file_handler->file_path);
}

static void
close_last_stream(file_handler_ptr file_handler)
{
  if (file_handler->file_stream)
    {
      fclose(file_handler->file_stream);
      file_handler->file_stream = NULL;
    }
}

void
deinit_file_handler(file_handler_ptr file_handler)
{
  close_last_stream(file_handler);
  free_path(file_handler);

  free(file_handler);
  file_handler = NULL;
}

const char *
get_filter_extension(const file_handler_ptr file_handler)
{
  return file_handler->filter_extension;
}

void
initialize_file_path(file_handler_ptr file_handler,
                     const char *directory, const char *file)
{
  close_last_stream(file_handler);
  free_path(file_handler);
  size_t dir_length = strlen(directory);
  size_t file_length = strlen(file);
  file_handler->file_path = malloc(sizeof (char) * (dir_length + file_length + 2));
  snprintf(file_handler->file_path, malloc_usable_size(file_handler->file_path),
           "%s/%s", directory, file);
}

const char *
get_filename(const file_handler_ptr file_handler)
{
  const char *filename = strrchr(file_handler->file_path, '/');
  if (!filename) return file_handler->file_path;
  return filename + 1;
}

FILE *
obtain_file_stream(file_handler_ptr file_handler)
{
  if (!file_handler->file_path)
    PRINT_ERROR_EXIT("Couldn't obtain path is empty");

  if (!file_handler->file_stream)
    {
      FILE *file = fopen(file_handler->file_path, "rm");
      if (!file) PRINT_SYSTEM_ERROR_EXIT("Couldn't open file");
      file_handler->file_stream = file;
    }

  return file_handler->file_stream;
}
